package com.example.study.jetpack

import androidx.compose.runtime.mutableStateListOf
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
import java.io.IOException

//https://juejin.cn/post/7048980213811642382
class MVI架构 {
    /*
    MVI架构 特点:单向数据流动+状态集中管理
    每个应用至少有两个层:
        界面层-在屏幕上显示应用数据
        数据层-提供所需要的应用数据
        可以额外添加一个网域层,以简化和复用界面层与数据层的交互

    界面层
        界面的作用是在屏幕上显示应用数据,并响应用户的点击.每当数据发生变化时,
        无论是用户还是网络,界面都随之跟心,以反映变化.不过,从数据层获取的应用数据的
        格式通常不同于UI需要展示的数据格式,因此我们需要将数据转化为页面的状态
        因此界面层一般分为两部分.即UI层与State Holder,State Holder的角色一般
        由ViewModel承担
        数据层的作用是存储和管理应用数据,以及提供对应用数据的访问权限,因此界面必须执行
        以下步骤:
        1.获取应用数据,并将其转换为UI可以轻松呈现的UIState
        2.订阅UIState,当页面状态发生改变时刷新UI
        3.接受用户的输入事件从而刷新UIState
        4.根据需要重复1-3
    数据层
    */
    /*如何定义UIState
        将界面需要的所有状态都封装在一个dataclass.与之前MVVM的主要区别之一也在这里
        即之前通常是一个State对应一个LiveData,而MVI架构强调对UIState的集中管理
    */
    data class userUiState(
        val isLogin:Boolean = false
    )
    /*以上UiState定义是不可变的,好处是保证即时提供应用的状态,便可专注发挥单一作用:
    读取UIState并相应的更新UI.因此,切勿直接在UI中修改UIState.违反这个原则会导致同一条信息有多个
    可信来源,从而导致数据不一致的问题

    UIState集中管理优缺点
    单个数据流的优点在于方便,减少模板代码,添加一个状态只需要给dataclass添加一个属性即可,
    可以有效的降低ViewModel与View的通信成本
    同时UIState集中管理可以实现累死MediatorLiveData的效果,比如可能只有在用户登录
    并付费才显示按钮可以如下
    */
    data class NewsUiState(
        val isSignedIn: Boolean = false,
        val isPremium: Boolean = false,
    ){
        val canBookmarkNews: Boolean get() = isSignedIn && isPremium
    }
    /*集中管理的缺点
        不相关的数据类型:UI所需的某些状态可能完全相互独立.在此情况下,将不同的状态捆绑在一起
        代价可能超过优势,尤其是其中某个状态跟心频率高于其他状态的更新频率
        UiState diffing:UiState对象中的字段越多,数据流就越有可能因为一个字段被
        更新发出.由于视图没有diffing机制来区分,因此视图都会跟心.可以使用LiveData或Flow
        使用distinctUntilChanged等方法来实现局部刷新 解决这个问题

    使用单向数据流管理UIState
        为了保证UI中不能修改状态,UIState元素师不可变的.如何更新数据
        一般使用ViewModel作为UIState容器,步骤
        1.ViewModel存储并公开UIState.UIState是经过ViewModell转换的应用数据
        2.UI层会向ViewModel发送用户事件通知
        3.ViewModel会处理用户操作并跟心UIState
        4.更新后的状态将反馈给UI进行呈现
        5.系统会对导致状态更改的所有事件重复以上操作
    为什么使用单向数据流动?
    1.数据一致性.界面只有一个可信来源
    2.可测试性.状态来源是独立的,因此可单独于界面进行测试
    3.可维护性.状态的更改遵循明确定义的模式,即状态更改是用户事件一起数据拉取来源共同的结果

    为了保证不在UI中修改状态,应该定义可变得StateFlow与一个不可变的stateFlow
        */
    class niewModel(): ViewModel() {
        private val _uiState = MutableStateFlow(NewsUiState())
        val uiState: StateFlow<NewsUiState> = _uiState.asStateFlow()
        var job = viewModelScope.launch {
            _uiState.value = NewsUiState(isSignedIn = true)
        }

    }
    /*订阅
    lifecycleScope.launch {
        repeatOnLifecycle(Lifecycle.State.STARTED) {
            viewModel.uiState.collect {
                // Update UI elements
            }
        }
    }*/

}